// @ts-ignore
import crypto, { Utf8AsciiLatin1Encoding } from 'crypto';
declare var fastXmlParser: any;

export const md5 = (str: string, encoding: Utf8AsciiLatin1Encoding = 'utf8') =>
  crypto
    .createHash('md5')
    .update(str, encoding)
    .digest('hex');

export const parseXML = (xml: string) => fastXmlParser.parse(xml);

export const checkXML = (str: string) => {
  const reg = /^(<\?xml.*\?>)?(\r?\n)*<xml>(.|\r?\n)*<\/xml>$/i;
  return reg.test(str.trim());
};

export const encryptRSA = (key: string, str: string) =>
  // @ts-ignore
  crypto.publicEncrypt(key, new Buffer(str)).toString('base64');

export const generateRandStr = (length = 16) => {
  const chars =
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let randStr = '';
  const maxPos = chars.length;
  while (length--) {
    randStr += chars[Math.floor(Math.random() * maxPos)];
  }
  return randStr;
};

export const buildXML = (obj: any) => {
  const list = Object.keys(obj)
    .map((key) => `<${key}><![CDATA[${obj[key]}]]></${key}>`)
    .join('');
  return `<xml>${list}</xml>`;
};

export const wechatSuccessNotify = {
  $raw: `<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>`,
  $type: 'text/xml'
};

/**
 * by using timestamp and six number sequence
 */
export const genNoV1 = () => {
  const lastTs = 0;
  let sequence = 0;
  const ts = +new Date();
  if (ts === lastTs) {
    sequence += 1;
  } else {
    sequence = 100000 + Math.floor(Math.random() * 100000);
  }
  const tail = sequence.toString();
  return ts.toString() + tail;
};

export const formatDate = (
  date: string | number | Date,
  fmt: string = 'YYYY-mm-dd HH:MM:SS'
) => {
  let ret;
  const d = new Date(date);
  const dat = new Date(d.setHours(d.getHours() + 8));
  const opt = {
    'Y+': dat.getFullYear().toString(),
    'm+': (dat.getMonth() + 1).toString(),
    'd+': dat.getDate().toString(),
    'H+': dat.getHours().toString(),
    'M+': dat.getMinutes().toString(),
    'S+': dat.getSeconds().toString()
  };
  // tslint:disable-next-line: forin
  for (const k in opt) {
    ret = new RegExp('(' + k + ')').exec(fmt);
    if (ret) {
      fmt = fmt.replace(
        ret[1],
        // @ts-ignore
        ret[1].length === 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
      );
    }
  }
  return fmt;
};

export const utc2gmt = (UTCDateString: string | number | Date) => {
  const utc = new Date(UTCDateString);
  const hour = utc.getHours();
  utc.setHours(hour + 8);
  return utc;
};
